package com.wetool.wechat.controller;

import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.wetool.common.model.Message;
import com.wetool.common.model.Result;
import com.wetool.common.wechat.PaymentMessage;
import com.wetool.common.wechat.ReviewMessage;
import com.wetool.common.wechat.WechatResult;
import com.wetool.wechat.entity.WechatAccountRelation;
import com.wetool.wechat.entity.WechatMerchantRelation;
import com.wetool.wechat.jpa.WechatAccountRelationRepo;
import com.wetool.wechat.jpa.WechatMerchantRelationRepo;
import com.wetool.wechat.model.official.ServerAuthRequest;
import com.wetool.wechat.model.official.message.AbstractMessage;
import com.wetool.wechat.service.MessageHandlerService;
import com.wetool.wechat.service.WechatOfficialService;
import com.wetool.wechat.util.MessageUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;

/**
 * 微信公众帐号接口
 */
@Api(description = "微信公众号接口")
@RequestMapping(value = "/official")
@RestController()
public class WechatOfficialAccountController {

    private static final Logger LOGGER = LoggerFactory.getLogger(WechatOfficialAccountController.class);

    @Value("${wechat.official-server.token}")
    private String serverToken;

    @Autowired
    private WechatOfficialService wechatOfficialService;

    @Autowired
    private MessageHandlerService messageHandlerService;

    @Autowired
    private WechatAccountRelationRepo wechatAccountRelationRepo;

    @Autowired
    private WechatMerchantRelationRepo wechatMerchantRelationRepo;

    /**
     * 微信第三方服务认证接口
     * 只有在该接口完成校验并正常返回微信服务器发来的随机字符串后，才能完成认证。
     *
     * @param request 认证请求参数
     * @return 成功则原样返回随机字符串，失败则返回其他
     */
    @GetMapping(value = "")
    public ResponseEntity<?> wechatGetRequest(ServerAuthRequest request) {

        LOGGER.info("进入接口 > 微信公众号Get请求(微信公众号服务器认证接口),参数:【{}】", request);

        String createString = request.createSignature(this.serverToken);

        boolean b = createString.equals(request.getSignature());
        LOGGER.info("签名验证：创建:{}------接收:{}---结果:{}", createString, request.getSignature(), b);

        String result;

        if (b) {
            result = request.getEchostr();
        } else {
            result = "error";
        }

        LOGGER.info("退出接口 < 微信公众号Get请求(微信公众号服务器认证接口),参数:【{}】", result);

        return ResponseEntity.ok(result);
    }

    /**
     * 微信统一消息入口，该接口的所有消息均为XML
     *
     * @return
     */
    @PostMapping(value = "")
    public ResponseEntity<?> wechatPostRequest(HttpServletRequest request, HttpServletResponse response) throws IOException {

        LOGGER.info("进入接口 > 微信公众号POST请求(微信公众号消息推送接口)");

        request.setCharacterEncoding("UTF-8");

        Map<String, Object> map = MessageUtil.convert(request);
        LOGGER.info("接受到消息:{}", map);
        AbstractMessage abstractMessage = this.messageHandlerService.dispatchMessage(map);

        LOGGER.info("结束接口 < 微信公众号POST请求(微信公众号消息推送接口)");

        if (abstractMessage == null) {
            return ResponseEntity.ok("SUCCESS");
        }

        XmlMapper xmlMapper = new XmlMapper();
        String xml = xmlMapper.writeValueAsString(abstractMessage);
        LOGGER.info(xml);
        return ResponseEntity.ok(xml);
    }

    /**
     * 公众号关注状态
     *
     * @return
     */
    @ApiOperation(value = "查询关注状态", notes = "查询当前用户公众号关注状态")
    @GetMapping(value = "/status")
    public ResponseEntity<?> followOfficialAccountStatus(@RequestParam(value = "unionId", required = false) String unionId, @RequestParam(value = "userId", required = false) Long userId) {
        LOGGER.info("进入接口 > 微信公众号关注状态查询接口,参数：unionId:{},userId:{}", unionId, userId);

        WechatAccountRelation account;
        Message<?> message;
        if (userId == null && !StringUtils.isEmpty(unionId)) {
            account = this.wechatAccountRelationRepo.findOne(unionId);
        } else if (userId != null && StringUtils.isEmpty(unionId)) {
            account = this.wechatAccountRelationRepo.findByUserId(userId);
        } else if (userId != null && !StringUtils.isEmpty(unionId)) {
            account = this.wechatAccountRelationRepo.findOne(unionId);
        } else {
            message = new Message<>(WechatResult.OFFICIAL_INTERFACE_PARAM_ERROR);
            LOGGER.info("退出接口 < 微信公众号关注状态查询接口,参数：{}", message);
            return ResponseEntity.ok(message);
        }

        if (account == null) {
            message = new Message<>(WechatResult.UNIONID_OR_USERID_INVALID, "unionId无效或用户信息未绑定");
            LOGGER.info("退出接口 < 微信公众号关注状态查询接口,参数：{}", message);
            return ResponseEntity.ok(message);
        }

        if (StringUtils.isEmpty(account.getOfficialOpenId())) {
            message = new Message<>(WechatResult.OFFICIAL_NOT_FOLLOW);
            LOGGER.info("退出接口 < 微信公众号关注状态查询接口,参数：{}", message);
            return ResponseEntity.ok(message);
        }
        message = new Message<>(Result.SUCCESS, "当前帐号已关注公众号");

        LOGGER.info("退出接口 < 微信公众号关注状态查询接口,参数：{}", message);

        return ResponseEntity.ok(message);
    }


    @ApiOperation(value = "商家微信公众号状态查询")
    @GetMapping(value = "/merchant/{merchantId}")
    public ResponseEntity<?> queryMerchantFollowStatus(@PathVariable long merchantId) {

        WechatMerchantRelation account = this.wechatMerchantRelationRepo.findOne(merchantId);
        if (account == null || StringUtils.isEmpty(account.getOfficialOpenId())) {
            return ResponseEntity.ok(new Message<>(Result.ERROR, "商户未关注微信公众号"));
        }
        return ResponseEntity.ok(new Message<>(Result.SUCCESS, "用户已经关注微信公众"));
    }


    @ApiOperation(value = "发送审批结果消息", notes = "发送模板消息")
    @PostMapping(value = "/message/review")
    public ResponseEntity<?> sendMessage(@RequestBody ReviewMessage reviewMessage, long userId) {
        LOGGER.info("进入接口 > 微信公众号POST请求(微信公众号消息推送接口)");

        Message<?> message = this.wechatOfficialService.sendMessage(reviewMessage, userId);

        LOGGER.info("进入接口 > 微信公众号POST请求(微信公众号消息推送接口)");

        return ResponseEntity.ok(message);
    }

    @ApiOperation(value = "发送支付结果消息", notes = "发送模板消息")
    @PostMapping(value = "/message/payment")
    public ResponseEntity<?> sendMessage(@RequestBody PaymentMessage paymentMessage, String openId) {
        LOGGER.info("进入接口 > 微信公众号POST请求(微信公众号消息推送接口)");

        Message<?> message = this.wechatOfficialService.sendMessage(paymentMessage, openId);

        LOGGER.info("进入接口 > 微信公众号POST请求(微信公众号消息推送接口)");
        return ResponseEntity.ok(message);
    }

    /**
     * 设置微信自定义菜单
     *
     * @return
     */
    @ApiOperation(value = "设置自定义菜单")
    @PostMapping(value = "/menu")
    public ResponseEntity<?> settingCustomMenu() {
        Message<?> message = this.wechatOfficialService.settingCustomMenu();
        return ResponseEntity.ok(message);
    }

}
